概览
最近在体验iOS 10Beta版的过程中,我发现iOS 10在锁屏界面的变动比较大,与之前的交互逻辑完全不同。与此同时,推送通知消息也有了改进,比如支持3D Touch,可以展示更多的信息,通知内容可以包含图片等等。按照逻辑推断iOS 10推送通知的API会有变化,于是,我赶紧查阅了Xcode 8Beta中的文档以及WWDC2016的视频,果然发现了玄机。
推送机制
推送机制在iOS 10上发生了一点变化。
iOS < 10.0
推送按照通知发送源分为本地推送和远程推送。
先说本地推送。本地推送是由设备上的app发起的,本地推送通知被加入到schedule中后,被诸如时间、位置、任务等触发通知而使其显示到设备上。当用户对通知消息做出反应,发起通知的app会得到回调。
再说远程推送。远程推送是由app的服务器通过网络连接发送的。app先注册远程通知得到APNS(Apple Push Notification Service)返回的device token,app的服务端将推送通知的负载连同device token发送给APNS。APNS根据device token将推送通知发送到用户的设备上。设备接收到通知后会展示在屏幕上供用户浏览和处理,之后app会得到用户处理的回调。
iOS >= 10.0
iOS 10新增了trigger
。依据字面意思理解就是推送通知的触发器,告诉设备什么时候触发通知显示在设备上。iOS 10支持四种类型的trigger
:push、timer interval、calendar and location。其中push属于远程推送,其他三种属于本地推送。
iOS 10推送通知的过程变成了这样:app注册通知,创建通知的内容,trigger,identifier,将这些放入UNNotificationRequest
对象中,最后将其放入schedule。
Notification Service Extensions
在iOS 10之前,推送通知的负载大小最多也就4KB,因而类似于声音、图像、视频等无法存储到推送通知当中。为了解决这个问题,iOS 10引入了新的扩展服务——Notification Service Extensions
。Notification Service Extensions
可以帮助我们在不打开app的情况下去下载或者是改变远程推送通知消息中的内容。由于推送通知的负载不足以存储多媒体文件本身,因而以URL的形式存储。一旦设备接收到来自于你的app的远程推送通知的负载,Notification Service Extensions
便去下载URL当中的资源文件,然后会在用户查看通知消息时展现给用户。
那么它是如何工作的呢?在通知的服务端,发送的通知会被service extension加工成两个部分:
mutable-content
字段告诉iOS在通知被发送之前通知中有内容要被service extension修改,my-attachment
字段包含了被下载内容的URL。
为了能让app的扩展服务能够处理通知消息,我们需要在app的Xcode project中添加notification service extension
。Xcode会生成一个包含UNNotificationServiceExtension
子类的文件。
这个文件包含两个需要被重写的方法。第一个方法用来下载URL中的内容并将其添加到通知当中。由于网络是不可靠的,因此我们还需要在此方法中处理网络发生错误的情况。第二个方法是用来处理第一个方法运行超时的情况,当attachment下载消耗太长的时间时,操作系统会执行serviceExtensionTimeWillExpire()
方法终止下载并发送类似于”best attempt”内容的通知。
Media Attachments
Media Attachments
是用来附着在推送通知上负责存储多媒体文件的URL。目前支持的多媒体文件类型包括常用的音频、视频和图片(包括GIF)格式。
|
|
Media Attachments
在本地推送与远程推送的工作机制有轻微差别。在本地推送中,它的media attachment
在app创建通知时就必须包含某个本地磁盘文件的URL。当通知生效时,那份文件会被拷贝一份随着通知一起发送出去。除此之外,不需要做别的工作。在远程推送中,远程通知服务会将media attachment
作为APNS通知负载的一部分发送出去。media attachment
中包含的URL的内容不限定必须是已经存在设备中的文件。然而,iOS 10无法自动发送attachment内容不存储在本地的通知,这就要借助到前面提到的Notification Service Extensions
。
Notification Content Extensions
如果我们想在通知中展现app中一样的界面内容时,该怎么办?Notification Content Extensions
派上用场了。Notification Content Extensions
与Notification Service Extensions
在通知中提供新的内容方面有相似之处,但两者有两个重要的区别。第一,Notification Content Extensions
在本地推送和远程推送当中都起作用,而Notification Service Extensions
只在远程推送中工作。第二,Notification Content Extensions
只能处理media attachment中的内容,而Notification Service Extensions
不仅能处理media attachment中的内容,更能在通知详情中展示整个的UIViewController
。
在上图中我们看到了日历通知的日历事件就是用到了Notification Content Extensions
。在Xcode项目中添加Notification Content Extensions
与Notification Service Extensions
的操作类似。
|
|
创建成功后,Xcode会生成一个storyboard文件、代码文件以及可以自定义contentn extension内容的info.plist文件。代码文件中包含了一个实现UNNotificationContentExtension
协议的UIViewController的子类。要想让它生效,我们需要实现协议中必须实现的方法,在storyboard中自定义view设置info.plist文件中的category ID。
结语
原理部分的内容就这么多了,关于推送的UserNotifications.framework代码方面的内容会放到下一篇中。